/////////////////////////////////////////////////////////////////////////
// MIT License
//
// Copyright (c) 2000-2011 OpenNETCF Consulting, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
////////////////////////////////////////////////////////////////////////

using System;
using System.Reflection;
using System.Drawing;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Windows.Forms;
using System.IO;
using OpenNETCF.Windows.Forms;
using OpenNETCF.Drawing.Imaging;

using OpenNETCF.Windows.Forms.Calendar.Properties;

namespace OpenNETCF.Windows.Forms.Calendar
{
    /// <summary>
    /// Base class for several calendar controls
    /// </summary>
    public class BaseCalendar : UserControl
    {
        #region Events
        /// <summary>
        /// Fired when the visible date range changes
        /// </summary>
        public event VisibleRangeChangedHandler VisibleRangeChanged;
        /// <summary>
        /// Optional delegate to provide cell label string via callback mechanism
        /// </summary>
        public event GetLabelHandler GetLabel;
        /// <summary>
        /// Optional delegate to provide cell painting via a callback
        /// </summary>
        public event DrawLabelHandler DrawLabel;
        /// <summary>
        /// Fired when the user select a specific data
        /// </summary>
        public event DateSelectedHandler DateSelected;

        #endregion

        #region Graphic objects
        /// <summary>
        /// Background brush for painting
        /// </summary>
        protected SolidBrush m_brBackground;
        /// <summary>
        /// Month foreground brush
        /// </summary>
        protected SolidBrush m_brMonthFG;
        /// <summary>
        /// Day background brush
        /// </summary>
        protected SolidBrush m_brDayBG;
        /// <summary>
        /// Day Foreground brush
        /// </summary>
        protected SolidBrush m_brDayFG;
        /// <summary>
        /// Weekend foreground brush
        /// </summary>
        protected SolidBrush m_brWeekendFG;
        /// <summary>
        /// Saturday foreground brush
        /// </summary>
        protected SolidBrush m_brSaturdayFG;
        /// <summary>
        /// Sunday foreground brush
        /// </summary>
        protected SolidBrush m_brSundayFG;
        /// <summary>
        /// Label background brush
        /// </summary>
        protected SolidBrush m_brLabelBG;
        /// <summary>
        /// Label  foreground brush
        /// </summary>
        protected SolidBrush m_brLabelFG;
        /// <summary>
        /// Selected day backcolor brush
        /// </summary>
        protected SolidBrush brush_SelectedDayBackColor;
        /// <summary>
        /// Selected day forecolor brush
        /// </summary>
        protected SolidBrush brush_SelectedDayForeColor;        
        /// <summary>
        /// Grid line color
        /// </summary>
        protected Pen m_penGrid;
        /// <summary>
        /// Frame color
        /// </summary>
        protected Pen m_penFrame;

        /// <summary>
        /// Offscreen graphics
        /// </summary>
        protected Graphics m_gxOff;
        /// <summary>
        /// Offscreen bitmap
        /// </summary>
        protected Bitmap m_bmOff;

        /// <summary>
        /// Font for the label
        /// </summary>
        protected Font m_fntLabel;
        /// <summary>
        /// Font for the month
        /// </summary>
        protected Font m_fntMonth;

        #endregion


        #region Internal data
        /// <summary>
        /// Constant DPI Setting for VGA support
        /// </summary>
        protected const int DPISETTING = 96;
        private int scale = -1;
        /// <summary>
        /// First day of week
        /// </summary>
        protected DayOfWeek m_firstDayOfWeek;
        /// <summary>
        /// Calendar items
        /// </summary>
        protected CalendarItem[] m_items;
        /// <summary>
        /// Calendar data items
        /// </summary>
        protected ICalendarDataProvider m_dataProvider;
        /// <summary>
        /// Current date
        /// </summary>
        protected DateTime m_date;
        /// <summary>
        /// Suspend layout
        /// </summary>
        protected bool m_fSuspendLayout;
        /// <summary>
        /// Recalculation required
        /// </summary>
        protected bool m_fRecalcRequired;
        /// <summary>
        /// Bounds of the top bar
        /// </summary>
        protected Rectangle m_rTopBar;
        /// <summary>
        /// Height of the week bar
        /// </summary>
        protected int m_weekBarHeight;
        /// <summary>
        /// Offset for the left side
        /// </summary>
        protected int m_leftOffset;

        #endregion

        #region Controls
        internal CalendarButton m_btnLeft, m_btnRight;
        /// <summary>
        /// Month button selection
        /// </summary>
        protected Button2 m_btnMonth;
        /// <summary>
        /// Year button selection
        /// </summary>
        protected Button2 m_btnYear;
        internal CalendarButton m_btnToday;
        /// <summary>
        /// Month context menu
        /// </summary>
        protected ContextMenu m_mnuMonth;
        /// <summary>
        /// Year context menu
        /// </summary>
        protected ContextMenu m_mnuYear;

        #endregion

#if EVAL_VERSION
        static BaseCalendar()
        {
            MessageBox.Show("This is an evaluation version of the OpenNETCF Calendar Controls 1.0.  To purchase you licensed copy please visit www.opennetcf.com.",
                "OpenNETCF Calendar Control 1.0",
                MessageBoxButtons.OK,
                MessageBoxIcon.Exclamation,
                MessageBoxDefaultButton.Button1);
        }
#endif
        /// <summary>
        /// Implements the basic functionality required by calendar controls
        /// </summary>
        public BaseCalendar()
        {
            m_fSuspendLayout = false;
            m_fRecalcRequired = false;
            SuspendLayout();
            
            Initialize();

            CreateControls();

            this.AutoScaleMode = AutoScaleMode.None;
            //this.Dock = DockStyle.Fill;

            Date = DateTime.Now.Date;
            //ResumeLayout();
        }

        /// <summary>
        /// Initializes the base calendar control to be used
        /// </summary>
        protected virtual void Initialize()
        {
            m_firstDayOfWeek = System.Globalization.DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek;
            m_items = new CalendarItem[0];
            BackColor = System.Drawing.SystemColors.Control;
            ForeColor = Color.Black;
            DayBackColor = Color.White;
            DayForeColor = Color.Black;
            LabelBackColor = Color.Navy;
            LabelForeColor = Color.White;
            this.SundayForeColor = WeekendForeColor = Color.Red;
            this.SaturdayForeColor = Color.Blue;
            this.SelectedDayBackColor = SystemColors.ActiveCaption;
            this.SelectedDayForeColor = SystemColors.ActiveCaptionText;
            GridColor = Color.Black;
            Font = new Font("Tahoma", 8, FontStyle.Regular);
            FontLabel = Font;
            FontMonth = new Font("Tahoma", 8, FontStyle.Bold);
        }

        /// <summary>
        /// Creates any controls needed to be functional
        /// </summary>
        protected virtual void CreateControls()
        {
            m_btnMonth = new Button2();
            m_btnYear = new Button2();
            m_btnMonth.BorderStyle = BorderStyle.None;
            m_btnYear.BorderStyle = BorderStyle.None;

            Controls.Add(m_btnMonth);
            Controls.Add(m_btnYear);

            m_btnLeft = new CalendarButton();
            m_btnRight = new CalendarButton();
            this.m_btnToday = new CalendarButton();

            //Setup the right button
            m_btnRight.BackColor = System.Drawing.SystemColors.Control;
            m_btnRight.BorderColor = System.Drawing.SystemColors.Control;
            if (this.ScaleSize > 1)
                m_btnRight.Image = Resources.RArrow_vga;
            else
                m_btnRight.Image = Resources.RArrow;
            m_btnRight.ImageAlign = OpenNETCF.Drawing.ContentAlignment2.MiddleCenter;
            m_btnRight.Location = new System.Drawing.Point(0, 0);
            m_btnRight.Size = new System.Drawing.Size(18 * this.ScaleSize, 18 * this.ScaleSize);
            m_btnRight.ActiveBackColor = SystemColors.Window;
            m_btnRight.ActiveBorderColor = SystemColors.ControlText;

            //Setup the left button
            m_btnLeft.BackColor = System.Drawing.SystemColors.Control;
            m_btnLeft.BorderColor = System.Drawing.SystemColors.Control;
            if (this.ScaleSize > 1)
                m_btnLeft.Image = Resources.LArrow_vga;
            else
                m_btnLeft.Image = Resources.LArrow;
            m_btnLeft.ImageAlign = OpenNETCF.Drawing.ContentAlignment2.MiddleCenter;
            m_btnLeft.Location = new System.Drawing.Point(0, 0);
            m_btnLeft.Size = m_btnRight.Size;
            m_btnLeft.ActiveBackColor = SystemColors.Window;
            m_btnLeft.ActiveBorderColor = SystemColors.ControlText;

            //Setup the today button
            this.m_btnToday.BackColor = System.Drawing.SystemColors.Control;
            this.m_btnToday.BorderColor = System.Drawing.SystemColors.Control;
            if (this.ScaleSize > 1)
                this.m_btnToday.Image = Resources.TodayDate_vga;
            else
                this.m_btnToday.Image = Resources.TodayDate;
            this.m_btnToday.ImageAlign = OpenNETCF.Drawing.ContentAlignment2.MiddleCenter;
            this.m_btnToday.Location = new System.Drawing.Point(0, 0);
            this.m_btnToday.Size = m_btnRight.Size;
            this.m_btnToday.ActiveBackColor = SystemColors.Window;
            this.m_btnToday.ActiveBorderColor = SystemColors.ControlText;

            //Add the controls
            Controls.Add(m_btnLeft);
            Controls.Add(m_btnRight);
            Controls.Add(this.m_btnToday);

            //Wire up the click events
            m_btnRight.Click += new EventHandler(btnRight_Click);
            m_btnLeft.Click += new EventHandler(btnLeft_Click);
            this.m_btnToday.Click += new EventHandler(btnToday_Click);
            m_btnMonth.Click += new EventHandler(btnMonth_Click);
            m_btnYear.Click += new EventHandler(btnYear_Click);

            m_mnuMonth = new ContextMenu();
            m_mnuYear = new ContextMenu();
        }

        #region Properties
        /// <summary>
        /// Gets or sets the current date of the control
        /// </summary>
        public DateTime Date
        {
            get { return m_date; }
            set
            {
                bool bRangeChanged = m_date.Month != value.Month || m_date.Year != value.Year;
                m_date = value;
                OnDateChanged();
                if (bRangeChanged)
                {
                    RecalculateYearAdnMonthButtons();
                    if (VisibleRangeChanged != null)
                    {
                        DateTime Start = Date.Date;
                        while (Start.DayOfWeek != DayOfWeek.Sunday)
                            Start = Start.AddDays(-1);
                        VisibleRangeChanged(Start, Start.AddDays(42));
                    }
                }
            }
        }

        /// <summary>
        /// Specifies an object that implements ICalendarDataProvider interface
        /// Used to provide controls with OpenNETCF.Windows.Forms.Calendar.CalendarItems for the visible date range
        /// </summary>
        public ICalendarDataProvider DataProvider
        {
            get { return m_dataProvider; }
            set
            {
                if (m_dataProvider != value)
                {
                    if (m_dataProvider != null)
                        m_dataProvider.ItemListChanged -= new ItemListChangedDelegate(dataProvider_ItemListChanged);
                    m_dataProvider = value;
                    if (m_dataProvider != null)
                        m_dataProvider.ItemListChanged += new ItemListChangedDelegate(dataProvider_ItemListChanged);
                }
            }
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        protected void dataProvider_ItemListChanged()
        {
            OnItemListChanged();
        }

        #region Overrides

        /// <summary>
        /// 
        /// </summary>
        protected virtual void OnItemListChanged()
        {
            Invalidate();
        }

        bool IsDateInRange(DateTime dt)
        {
            DateTime Start = new DateTime(Date.Year, Date.Month, 1);
            while (Start.DayOfWeek != DayOfWeek.Sunday)
                Start = Start.AddDays(-1);
            return (dt >= Start && dt < Start.AddDays(42));
        }

        /// <summary>
        /// Gets or sets the backcolor of the control
        /// </summary>
        public override Color BackColor
        {
            get { return base.BackColor; }
            set
            {
                base.BackColor = value;
                CreateBrush(ref m_brBackground, value);
            }
        }

        /// <summary>
        /// Gets or sets the forecolor of the control
        /// </summary>
        public override Color ForeColor
        {
            get { return m_brMonthFG.Color; }
            set { CreateBrush(ref m_brMonthFG, value); }
        }

        /// <summary>
        /// Color to paint the background of the cell date
        /// </summary>
        public virtual Color DayBackColor
        {
            get { return m_brDayBG.Color; }
            set { CreateBrush(ref m_brDayBG, value); }
        }

        /// <summary>
        /// Color to paint the foreground of the cell date
        /// </summary>
        public virtual Color DayForeColor
        {
            get { return m_brDayFG.Color; }
            set { CreateBrush(ref m_brDayFG, value); }
        }

        /// <summary>
        /// Gets or sets the color to paint the label background
        /// </summary>
        public virtual Color LabelBackColor
        {
            get { return m_brLabelBG.Color; }
            set { CreateBrush(ref m_brLabelBG, value); }
        }

        /// <summary>
        /// Gets or set the text color of the label
        /// </summary>
        public virtual Color LabelForeColor
        {
            get { return m_brLabelFG.Color; }
            set { CreateBrush(ref m_brLabelFG, value); CreatePen(ref m_penFrame, value); }
        }

        /// <summary>
        /// Color for weekend date text
        /// </summary>
        public virtual Color WeekendForeColor
        {
            get { return m_brWeekendFG.Color; }
            set { CreateBrush(ref m_brWeekendFG, value); }
        }

        /// <summary>
        /// Gets or sets the Color Saturday
        /// </summary>
        public virtual Color SaturdayForeColor
        {
            get { return this.m_brSaturdayFG.Color; }
            set { CreateBrush(ref m_brSaturdayFG, value); }
        }

        /// <summary>
        /// Gets or sets the Color Sunday
        /// </summary>
        public virtual Color SundayForeColor
        {
            get { return this.m_brSundayFG.Color; }
            set { CreateBrush(ref m_brSundayFG, value); }
        }

        /// <summary>
        /// Gets or sets the color of the control's grid
        /// </summary>
        public virtual Color GridColor
        {
            get { return m_penGrid.Color; }
            set { CreatePen(ref m_penGrid, value); OnGridColorChanged(); }
        }

        /// <summary>
        /// Gets or sets the font of the control
        /// </summary>
        public override Font Font
        {
            get
            {
                return base.Font;
            }
            set
            {
                base.Font = value;
                OnFontChanged();
            }
        }

        /// <summary>
        /// Gets or sets the selected day back color
        /// </summary>
        public Color SelectedDayBackColor
        {
            get
            {
                return this.brush_SelectedDayBackColor.Color;
            }
            set
            {
                this.CreateBrush(ref this.brush_SelectedDayBackColor, value);
            }
        }

        /// <summary>
        /// Gets or sets the selected day fore color
        /// </summary>
        public Color SelectedDayForeColor
        {
            get
            {
                return this.brush_SelectedDayForeColor.Color;
            }
            set
            {
                this.CreateBrush(ref this.brush_SelectedDayForeColor, value);
            }
        }


        #endregion

        /// <summary>
        /// Gets or sets the font to use for the label
        /// </summary>
        public virtual Font FontLabel
        {
            get { return m_fntLabel; }
            set { m_fntLabel = value; OnLabelFontChanged(); }
        }

        /// <summary>
        /// Month button font
        /// </summary>
        public Font FontMonth
        {
            get {  return m_fntMonth; }
            set
            {
                m_fntMonth = value;
                OnMonthFontChanged();
            }
        }

        /// <summary>
        /// First day of week. By default is set to the current culture first day of week
        /// </summary>
        public DayOfWeek FirstDayOfWeek
        {
            get { return m_firstDayOfWeek; }
            set { m_firstDayOfWeek = value; this.Invalidate(); }
        }


        #region Event handlers
        internal virtual void btnMonth_Click(object sender, EventArgs e)
        {
            m_mnuMonth.MenuItems.Clear();
            DateTime dt = new DateTime(2004, 1, 1);
            for (int i = 0; i < 12; i++)
            {
                MenuItem item = new MenuItem();
                item.Text = dt.ToString("MMMM");
                item.Checked = dt.Month == Date.Month;
                item.Click += new EventHandler(Month_Click);
                m_mnuMonth.MenuItems.Add(item);
                dt = dt.AddMonths(1);
            }
            m_mnuMonth.Show(this, new Point(m_btnMonth.Left, m_btnMonth.Bottom));
            Invalidate();
        }

        internal virtual void btnYear_Click(object sender, EventArgs e)
        {
            m_mnuYear.MenuItems.Clear();
            DateTime dt = new DateTime(Date.Year - 5, 1, 1);
            for (int i = 0; i < 10; i++)
            {
                MenuItem item = new MenuItem();
                item.Text = dt.ToString("yyyy");
                item.Checked = dt.Year == Date.Year;
                item.Click += new EventHandler(Year_Click);
                m_mnuYear.MenuItems.Add(item);
                dt = dt.AddYears(1);
            }
            m_mnuYear.Show(this, new Point(m_btnYear.Left, m_btnYear.Bottom));
        }

        internal virtual void Month_Click(object sender, EventArgs e)
        {
            Date = new DateTime(Date.Year, m_mnuMonth.MenuItems.IndexOf(sender as MenuItem) + 1, Date.Day);
        }

        internal virtual void Year_Click(object sender, EventArgs e)
        {
            Date = new DateTime(int.Parse((sender as MenuItem).Text), Date.Month, Date.Day);
        }

        internal virtual void btnRight_Click(object sender, EventArgs e)
        {
            Date = Date.AddDays(7);
        }

        internal virtual void btnLeft_Click(object sender, EventArgs e)
        {
            Date = Date.AddDays(-7);
        }

        internal virtual void btnToday_Click(object sender, EventArgs e)
        {
            Date = DateTime.Now;
        }

        #endregion


        #region Overrides
        /// <summary>
        /// Invalidates the control
        /// </summary>
        protected virtual void OnFontChanged()
        {
            Invalidate();
        }

        /// <summary>
        /// Invalidates the control
        /// </summary>
        protected virtual void OnMonthFontChanged()
        {
            RecalculateYearAdnMonthButtons();
            this.Invalidate(this.m_rTopBar);
        }

        /// <summary>
        /// Invalidates the control
        /// </summary>
        protected virtual void OnLabelFontChanged()
        {
            Invalidate(new Rectangle(0, 0, this.Width, this.Height));
        }

        /// <summary>
        /// Invalidates the control
        /// </summary>
        protected virtual void OnGridColorChanged()
        {
            Invalidate();
        }

        /// <summary>
        /// Invalidates the control
        /// </summary>
        protected virtual void OnDateChanged()
        {
            Invalidate();
        }

        /// <summary>
        /// Rasise the System.Windows.Forms.Control.HandleCreated event
        /// </summary>
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            ResumeLayout();
        }

        /// <summary>
        /// Raises the System.Windows.Forms.Control.Paint event
        /// </summary>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (this.m_gxOff != null)
            {
                DrawControl(m_gxOff, e.ClipRectangle);
                e.Graphics.DrawImage(m_bmOff, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
            }
        }

        /// <summary>
        /// Raises the OpenNETCF.Windows.Forms.Calendar.BaseCalendar.DateSelected event
        /// </summary>
        protected virtual void OnDateSelected(DateTime newDate)
        {
            if (DateSelected != null)
                DateSelected(newDate);
        }

        /// <summary>
        /// Raises the OpenNETCF.Windows.Forms.Calendar.BaseCalendar.DrawLabel event
        /// </summary>
        protected virtual bool OnDrawLabel(DateTime date, Rectangle rectCell, Graphics gxCell)
        {
            if (DrawLabel != null)
            {
                DrawLabel(this, date, rectCell, gxCell);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Raises the OpenNETCF.Windows.Forms.Calendar.BaseCalendar.GetLabel event
        /// </summary>
        protected virtual string OnGetLabel(DateTime date)
        {
            if (GetLabel != null)
            {
                return GetLabel(date);
            }
            return "";
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //base.OnPaintBackground (e);
        }

        /// <summary>
        /// Raises the System.Windows.Forms.Control.Resize event
        /// </summary>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            
            //Adjust the controls
            m_btnRight.Location = new Point(Width - m_btnRight.Width - this.Padding, 1)  ;
            m_btnLeft.Location = new Point(m_btnRight.Left - m_btnLeft.Width - 3, m_btnRight.Top);
            m_btnToday.Location = new Point(m_btnLeft.Left - m_btnToday.Width - 3, m_btnRight.Top);

            CreateObjects();
        }

        /// <summary>
        /// Gets the padding for the control
        /// </summary>
        protected int Padding
        {
            get
            {
                return 4 * this.ScaleSize;
            }
        }

        /// <summary>
        /// Draws the calendar control.  BaseCalendar is an empty method and should be overriden
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rClip"></param>
        protected virtual void DrawControl(Graphics g, Rectangle rClip)
        {
        }

        #endregion

        /// <summary>
        /// Recalculates the year and month buttons
        /// </summary>
        protected virtual void RecalculateYearAdnMonthButtons()
        {
            if (m_gxOff == null)
                return;
            if (m_btnMonth != null)
            {
                m_btnMonth.Font = FontMonth;
                SizeF szMonth = m_gxOff.MeasureString(m_btnMonth.Text, FontMonth);
                szMonth.Height += 4;
                szMonth.Width += 4;
                m_btnMonth.Location = new Point(4, 2);
                m_btnMonth.Size = new Size((int)szMonth.Width, (int)szMonth.Height);
            }
            if (m_btnYear != null)
            {
                m_btnYear.Font = FontMonth;
                SizeF szYear = m_gxOff.MeasureString(m_btnYear.Text, FontMonth);
                szYear.Height += 4;
                szYear.Width += 4;
                m_btnYear.Location = new Point(m_btnMonth.Right + 3, m_btnMonth.Top);
                m_btnYear.Size = new Size((int)szYear.Width, (int)szYear.Height);
            }
        }

        #region internal methods

        /// <summary>
        /// Creates offscreen buffer objects
        /// </summary>
        protected virtual void CreateObjects()
        {
            if (m_gxOff != null)
                m_gxOff.Dispose();
            if (m_bmOff != null)
                m_bmOff.Dispose();
            if (Size != Size.Empty)
            {
                m_bmOff = new Bitmap(Size.Width, Size.Height);
                m_gxOff = Graphics.FromImage(m_bmOff);
            }
        }

        /// <summary>
        /// Suspends the layout of the control
        /// </summary>
        protected new void SuspendLayout()
        {
            base.SuspendLayout();
            m_fSuspendLayout = true;
        }

        /// <summary>
        /// Resumes the layout of the control
        /// </summary>
        protected new void ResumeLayout()
        {
            base.ResumeLayout();
            m_fSuspendLayout = false;
            if (m_fRecalcRequired)
                Recalculate();
        }

        /// <summary>
        /// Recalculates the control
        /// </summary>
        protected virtual void Recalculate()
        {
            // Base implementation simply clears the flag
            m_fRecalcRequired = false;
        }

        private void CreateBrush(ref SolidBrush br, Color clr)
        {
            if (br != null)
                br.Dispose();
            br = new SolidBrush(clr);
        }

        private void CreatePen(ref Pen pen, Color clr)
        {
            if (pen != null)
                pen.Dispose();
            pen = new Pen(clr);
        }

        internal int ScaleSize
        {
            get
            {
                if (this.scale == -1)
                {
                    using (Graphics g = this.CreateGraphics())
                    {
                        this.scale = (int)g.DpiX / DPISETTING;
                    }
                }
                return scale;
            }
        }
        #endregion

        /// <summary>
        /// Releases the unmanaged resources of OpenNETCF.Windows.Forms.Calendar.BaseCalendar control
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (disposing)
            {
                m_bmOff.Dispose();
                m_brBackground.Dispose();
                m_brDayBG.Dispose();
                m_brDayFG.Dispose();
                m_brLabelBG.Dispose();
                m_brLabelFG.Dispose();
                m_brMonthFG.Dispose();
                m_brWeekendFG.Dispose();
                m_fntLabel.Dispose();
                m_fntMonth.Dispose();
                m_gxOff.Dispose();
                m_penFrame.Dispose();
                m_penGrid.Dispose();
            }
        }
        
    }
    
    #region Delegate definitions
    /// <summary>
    /// Represents the method that will handle the event when a date is selected
    /// </summary>
    /// <param name="date">The date selected within the control</param>
    public delegate void DateSelectedHandler(DateTime date);
    /// <summary>
    /// Represents the method that will handle the event when the visible date range has changed
    /// </summary>
    /// <param name="Start">the start date visible</param>
    /// <param name="End">the end date visible</param>
    public delegate void VisibleRangeChangedHandler(DateTime Start, DateTime End);
    /// <summary>
    /// Represents the method that will handle the event when GetLabel event is fired
    /// </summary>
    /// <param name="date">the date associated with the label</param>
    /// <returns>The label to display</returns>
    public delegate string GetLabelHandler(DateTime date);
    /// <summary>
    /// Represents the method that will handle the event when the DrawLabel event is fired
    /// </summary>
    /// <param name="sender">control raising the event</param>
    /// <param name="date">the date currently being drawn</param>
    /// <param name="rectCell">the bounds of the cell</param>
    /// <param name="gxCell">the graphics object for the cell</param>
    public delegate void DrawLabelHandler(BaseCalendar sender, DateTime date, Rectangle rectCell, Graphics gxCell);
    #endregion
}
